import {API_URL} from '../config.js';

/**
 * http 封装
 * @param options
 * @returns {*}
 */
export default function http(options) {
	const url = options.api ? API_URL + '/' + options.api : options.url;
	const oldFail = options.fail,
		oldComplete = options.complete;

	options = Object.assign({
		url: url,
		method: 'GET',
		isShowLoading: true,
		showLoadingText: '请稍后...',
	}, options);

	//请求前数据处理
	options = http.onRequest(options);
	//如果返回false、null、undefined,则说明取消本次请求
	if (!options) return;

	if (options.isShowLoading) wx.showLoading({title: options.showLoadingText});

	if (options.loginInvalidCount === undefined)
		options.loginInvalidCount = 0;

	options.success = (res) => {
		const flag = http.onCheckResponse(res);
		if (flag === 1) {
			options.callback && options.callback.call(options.thisArg, http.onResponseData(res.data));
		} else if (flag === -1) {
			//最多登录失效一次，否则可能造成无限回调
			if (options.loginInvalidCount > 0) {
				http.onLoginInvalidTip();
			} else {
				http.onLogin(options);
			}
		} else {
			console.error(res);
			//如果返回false，则不在执行后面的操作
			if (options.error && options.error.call(options.thisArg, res) === false) return;
			options.isShowToasted = true;
			wx.showToast({title: res.data.msg || "服务器繁忙", icon: 'none'});
		}
	};
	options.fail = (err) => {
		console.error(err);
		//如果返回false，则不在执行后面的操作
		if (oldFail && oldFail.call(options.thisArg, err) === false) return;
		options.isShowToasted = true;
		wx.showToast({title: '网络错误，请稍后重试~', icon: 'none'});
	};
	options.complete = (res) => {
		//兼容微信比较操蛋的问题
		if (options.isShowLoading && !options.isShowToasted) wx.hideLoading();
		oldComplete && oldComplete.call(options.thisArg, res);
	};

	return wx.request(options);
}

/**
 * Get 请求
 * @param {string} api
 * @param {*} [data]
 * @param {function} [callback]
 * @param {*} [options]
 * @returns {*}
 */
http.get = function (api, data, callback, options) {
	return this(Object.assign(options || {}, {api, data, callback}));
};

/**
 * Post 请求
 * @param {string} api
 * @param {*} [data]
 * @param {function} [callback]
 * @param {*} [options]
 * @returns {*}
 */
http.post = function (api, data, callback, options) {
	return this(Object.assign(options || {}, {api, data, callback, method: 'POST'}));
};

/**
 * 请求前监听
 * @param {*} config
 * @return {*}
 */
http.onRequest = (config) => {
	console.warn('请实现 http.onRequest(config) 接口', config);
	return config;
};

/**
 * 登录监听
 * @param {*} config
 */
http.onLogin = (config) => {
	console.warn('请实现 http.onLogin(config) 接口', config);
};

/**
 * 登录失效提示
 */
http.onLoginInvalidTip = () => {
};

/**
 * 检查返回服务器返回业务状态
 * @param {*} response
 * @return {number}
 */
http.onCheckResponse = (response) => {
	console.warn('请实现 http.onCheckResponse(response) 接口', response);
	return 1;
};

/**
 * 请求后数据处理
 * @param {*} data
 */
http.onResponseData = (data) => {
	return data;
};

/**
 * 上传文件
 * @param {*} options
 */
http.upload = (options) => {
	const url = options.api ? API_URL + '/' + options.api : options.url;
	const dataType = options.dataType || 'json';
	const {name, success, fail, complete, start, end, onProgressUpdate} = options;
	let count = 0, result = new Array(options.files.length);

	//生成上传器
	const uploaders = options.files.map((file, index) => {
		if (typeof file !== 'object') file = {path: file, name: name};

		let task = null;
		return Object.assign({}, file, {
			update: (onComplete) => {
				start && start.call(options.thisArg, {index: index, file: file});
				task = wx.uploadFile({
					url: url,
					filePath: file.path,
					name: file.name,
					header: options.header,
					formData: options.formData,
					success: (res) => {
						if (dataType === 'json') {
							try {
								result[index] = JSON.parse(res.data);
							} catch (e) {
								result[index] = {errMsg: e.message};
								fail && fail.call(options.thisArg, {index: index, result: result[index]});
								return;
							}
						} else {
							result[index] = res.data;
						}
						success && success.call(options.thisArg, {index: index, result: result[index]});
					},
					fail: (res) => {
						result[index] = res;
						fail && fail.call(options.thisArg, {index: index, result: res});
					},
					complete: (res) => {
						onComplete && onComplete.call(options.thisArg, {index: index, result: res});
						complete && complete.call(options.thisArg, {index: index, result: res});
					},
				});

				if (!task) return;
				task.onProgressUpdate((progress) => {
					onProgressUpdate && onProgressUpdate.call(options.thisArg, {index: index, progress: progress});
				});
			},
			cancel: () => {
				if (task) task.abort();
			}
		})
	});

	function handler(index) {
		uploaders[index].update(() => {
			if (!options.multiple && index < uploaders.length - 1) {
				handler(index + 1);
			}
			count++;
			if (count >= uploaders.length) {
				end && end.call(options.thisArg, result);
			}
		});
	}

	if (options.multiple) { //同时上传，速度快
		for (let i = 0; i < uploaders.length; i++) {
			handler(i);
		}
	} else { //逐个上传，省资源
		handler(0);
	}

	return uploaders;
};
